from typing import Tuple

from appium.webdriver.common.appiumby import AppiumBy
from appium.webdriver.webelement import WebElement
from utils.logger import get_logger
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
import allure
import time
import pytest
from utils.time_recorder import time_record
import logging



class BasePage:
    def __init__(self,driver):
        self.driver = driver
        self.logger = get_logger()


    @time_record
    @allure.step("查找元素: {locator}")
    def find_element(self, locator,condition='present'):
        """查找元素"""
        start_time = time.time()
        try:
            self.logger.info(f"查找元素: {locator}")
            els = WebDriverWait(self.driver,10).until(EC.presence_of_all_elements_located(locator))
            logging.info(f"""元素位置: {els[0].location} 尺寸: {els[0].size} 是否可见: {els[0].is_displayed()} 是否启用: {els[0].is_enabled()} 文本: {els[0].text}""")
            if len(els) > 1:
                self.logger.info(f"警告：找到 {len(els)} 个相同 ID 的元素！")
            else:
                return els[0]
        except TimeoutError as e:
            self.logger.error(f"元素等待超时，实际耗时: {time.time() - start_time:.2f}秒,元素： {locator}")
            raise e
        except Exception as e:
            self.logger.info(f"元素查找失败：{locator},原因：{e}")
            raise e

    @allure.step("查找多个元素: {locator}")
    def find_elements(self, locator, condition='present') :
        """查找多个元素"""
        start_time = time.time()
        try:
            self.logger.info(f"查找多个元素: {locator}")
            if condition == 'present':
                elements = WebDriverWait(self.driver, timeout=10).until(
                    EC.presence_of_all_elements_located(locator)
                )
            # 同样可扩展其他 condition 处理逻辑，如 'visible'
            # elif condition == 'visible':
            #     elements = WebDriverWait(self.driver, timeout=10).until(
            #         EC.visibility_of_all_elements_located(locator)
            #     )

                if elements:
                    self.logger.info(f"找到 {len(elements)} 个符合定位的元素")
                    # 可按需打印每个元素的详细信息，这里简单打印第一个元素示例
                    first_el = elements[0]
                    logging.info(
                        f"""第一个元素位置: {first_el.location} 尺寸: {first_el.size} 是否可见: {first_el.is_displayed()} 是否启用: {first_el.is_enabled()} 文本: {first_el.text}"""
                    )
                return elements
        except TimeoutError as e:
            elapsed_time = time.time() - start_time
            self.logger.error(
                f"元素等待超时，实际耗时: {elapsed_time:.2f}秒, 元素: {locator}")
            raise e
        except Exception as e:
            self.logger.info(f"元素查找失败: {locator}, 原因: {e}")
            raise e

    @time_record
    @allure.step("判断元素是否存在: {locator}")
    def is_element_exist(self, locator: Tuple[str, str], timeout: int = 10):
        """判断元素是否存在"""
        try:

            self.driver.find_element(*locator)
            self.logger.info(f"元素存在: {locator}")
            return True
        except Exception as e:
            self.logger.info(f"元素不存在：{locator},原因：{e}")
            return False

    @time_record
    @allure.step("点击元素: {locator}")
    def click(self, locator: Tuple[str, str]) -> None:
        """点击元素"""
        try:
            self.logger.info(f"点击元素: {locator}")
            self.find_element(locator).click()
        except Exception as e:
            self.logger.info(f"元素点击失败：{locator},原因：{e}")
            raise e

    @time_record
    @allure.step("输入文本:{text} ---> {locator}")
    def send_keys(self, locator: Tuple[str, str], text: str) -> None:
        """输入文本"""
        try:
            self.logger.info(f"输入文本：'{text}' 到这个位置： {locator}")
            element = self.find_element(locator)
            element.clear()
            element.send_keys(text)
        except Exception as e:
            self.logger.info(f"输入文本'{text}'到元素失败{locator},原因：{e}")
            raise e

    @time_record
    @allure.step("获取元素文本: {locator}")
    def get_text(self, locator: Tuple[str, str]) -> str:
        """获取元素文本"""
        try:
            self.logger.info(f"获取这个元素的文本: {locator}")
            result = self.find_element(locator).text
            self.logger.info(f"获取结果为: {result}")
            return result
        except Exception as e:
            self.logger.info(f"获取元素文本属性失败{locator},原因：{e}")
            raise e

    @time_record
    @allure.step("判断元素是否显示: {locator}")
    def is_displayed(self, locator: Tuple[str, str]) -> bool:
        """检查元素是否显示"""
        try:
            self.logger.info(f"元素显示{locator}")
            return self.find_element(locator).is_displayed()
        except Exception:
            self.logger.info(f"元素不显示{locator}")
            return False

    @time_record
    @allure.step("获取页面toast提示")
    def get_toast_text(self,timeout=2):
        try:
            self.logger.info(f"等待获取toast提示")
            # 直接通过 Toast 的类名定位
            toast_loc = (AppiumBy.XPATH, "//*[@class='android.widget.Toast']")
            toast_el = WebDriverWait(self.driver, timeout).until(
                EC.presence_of_element_located(toast_loc))
            toast_text = toast_el.text
            self.logger.info(f"成功获取toas提示：{toast_text}")
            return toast_text
        except Exception as e:
            self.logger.info(f"没有获取到toast提示，原因：{e}")
            return None

    @time_record
    @allure.step("滑动到页面底部")
    def scroll_until_bottom(self, max_attempts=5):
        self.logger.info(f'滑动到底部')
        for _ in range(max_attempts):
            try:
                # 尝试定位底部的某个元素（如"已经到底了"文本）
                self.driver.find_element(AppiumBy.XPATH, "//*[@text='已经到底了']")
                break  # 找到则退出循环
            except:
                # 未找到则滑动一次
                window_size = self.driver.get_window_size()
                self.driver.swipe(
                    window_size["width"] * 0.5,
                    window_size["height"] * 0.8,
                    window_size["width"] * 0.5,
                    window_size["height"] * 0.2,
                    duration=1000
                )

    @time_record
    @allure.step("判断是否被选中")
    def is_element_selected(self, locator):
        self.find_element(locator).is_selected()


